<template>
  <el-dialog
    :title="isNewRef ? modalConfig.header.newTitle : modalConfig.header.editTitle"
    v-model="dialogVisible"
    :width="modalConfig.modalWidth"
    center
    @close="cancel"
  >
    <div class="form">
      <el-form
        ref="formRef"
        :inline="modalConfig.formIsInline"
        :model="formData"
        :label-width="modalConfig.formlabelWidth"
        :rules="rules"
      >
        <el-row :gutter="20">
          <template v-for="(item, i) in modalConfig.formItems" :key="i">
            <template v-if="item.span">
              <el-col :span="item.span">
                <template v-if="item.type === 'input'">
                  <el-form-item :label="item.label" :prop="item.prop">
                    <el-input v-model="formData[item.prop]" :placeholder="item.placeholder" />
                  </el-form-item>
                </template>

                <template v-else-if="item.type === 'textarea'">
                  <el-form-item :label="item.label" :prop="item.prop">
                    <el-input type="textarea" v-model="formData[item.prop]" :placeholder="item.placeholder" />
                  </el-form-item>
                </template>

                <template v-else-if="item.type === 'select'">
                  <el-form-item :label="item.label" :prop="item.prop">
                    <el-select v-model="formData[item.prop]" :placeholder="item.placeholder">
                      <template v-for="(iten, j) in item.options" :key="j">
                        <el-option :value="iten.value + ''" :label="iten.label" />
                      </template>
                    </el-select>
                  </el-form-item>
                </template>

                <template v-else-if="item.type === 'custom'">
                  <!-- 需要标题，是form中元素 -->
                  <template v-if="item.isNeedlabel">
                    <el-form-item :label="item.label" :prop="item.prop">
                      <slot :name="item.slotName" />
                    </el-form-item>
                  </template>

                  <!-- 不需要标题，不是form中的元素 -->
                  <template v-else>
                    <slot :name="item.slotName" />
                  </template>
                </template>
              </el-col>
            </template>

            <template v-else>
              <el-col :lg="item.lg" :md="item.md" :sm="item.sm">
                <template v-if="item.type === 'input'">
                  <el-form-item :label="item.label" :prop="item.prop">
                    <el-input v-model="formData[item.prop]" :placeholder="item.placeholder" />
                  </el-form-item>
                </template>

                <template v-else-if="item.type === 'select'">
                  <el-form-item :label="item.label" :prop="item.prop">
                    <el-select v-model="formData[item.prop]" :placeholder="item.placeholder">
                      <template v-for="(iten, j) in item.options" :key="j">
                        <el-option :value="iten.value + ''" :label="iten.label" />
                      </template>
                    </el-select>
                  </el-form-item>
                </template>

                <template v-else-if="item.type === 'textarea'">
                  <el-form-item :label="item.label" :prop="item.prop">
                    <el-input type="textarea" v-model="formData[item.prop]" :placeholder="item.placeholder" />
                  </el-form-item>
                </template>

                <template v-else-if="item.type === 'custom'">
                  <template v-if="item.isNeedlabel">
                    <el-form-item :label="item.label" :prop="item.prop">
                      <slot :name="item.slotName" />
                    </el-form-item>
                  </template>

                  <template v-else>
                    <slot :name="item.slotName" />
                  </template>
                </template>
              </el-col>
            </template>
          </template>
        </el-row>
      </el-form>
    </div>

    <template #footer>
      <span>
        <el-button @click="cancel">取消</el-button>
        <el-button type="primary" @click="confirm">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
  import { nextTick, reactive, ref, watch } from 'vue'
  import useSystemStore from '@/store/main/system/system'
  import type { IModalConfig } from '.'
  import type { FormInstance, FormRules } from 'element-plus'

  interface IProp {
    modalConfig: IModalConfig
    otherInfo?: any
  }

  const $props = withDefaults(defineProps<IProp>(), {})
  const $emits = defineEmits(['reOtherInfo'])

  const dialogVisible = ref<boolean>(false)
  const isNewRef = ref<boolean>(false)
  const editData = ref<any>(null)

  // form custom 参数
  watch(
    () => $props.otherInfo,
    (newVal) => {
      if (dialogVisible.value) {
        for (let item of $props.modalConfig.formItems) {
          // 自定义插槽并且包含在form表单中
          if (item.type === 'custom' && item.isNeedlabel) {
            formData[item.prop] = newVal[item.prop]
          }

          // 自定义插槽并且不包含在form表单中
          if (item.type === 'custom' && !item.isNeedlabel) {
            otherFomrDate[item.prop] = newVal[item.prop]
          }
        }
      }
    },
    { deep: true }
  )

  // 初始化formData(无初始值，只是单纯初始表单数据模板), rules
  const initalData: any = {}
  const initOtherFormData: any = {}
  const initalRules: any = {}
  for (const item of $props.modalConfig.formItems) {
    if ((item.isNeedlabel && item.slotName) || (!item.isNeedlabel && !item.slotName)) {
      initalData[item.prop] = item.initalValue ?? ''
      initalRules[item.prop] = item.rules
    }

    if (!item.isNeedlabel && item.slotName) {
      initOtherFormData[item.prop] = item.initalValue ?? ''
    }
  }
  const formData = reactive<any>(initalData)
  const otherFomrDate = reactive<any>(initOtherFormData)
  const rules = reactive<FormRules<any>>(initalRules)
  const formRef = ref<FormInstance>()
  const systemStore = useSystemStore()

  async function setDialogVisible(isNew: boolean = true, itemData?: any) {
    await nextTick()
    // 清除上一次表单的校验
    formRef.value?.resetFields()

    isNewRef.value = isNew
    // 编辑
    if (!isNew && itemData) {
      for (const key in formData) {
        formData[key] = itemData[key] + ''
      }
      delete formData.password
      editData.value = itemData
    } else {
      // 清除formItem自定义插槽中数据
      $emits('reOtherInfo')
      for (const key in formData) {
        const item = $props.modalConfig.formItems.find((o) => o.prop === key)
        if ((item?.isNeedlabel && item?.slotName) || (!item?.isNeedlabel && !item?.slotName)) {
          formData[key] = item ? item.initalValue : ''
        }

        if (!item?.isNeedlabel && item?.slotName) {
          otherFomrDate[key] = item.initalValue ?? ''
        }
      }
      editData.value = null
    }
    dialogVisible.value = true
  }
  async function confirm() {
    await formRef.value?.validate()

    if (isNewRef.value) {
      systemStore
        .newPageDataAction($props.modalConfig.pageName, { ...formData, ...otherFomrDate })
        .then(() => {
          ElMessage.success(`新建${$props.modalConfig.titleTip}成功`)
        })
        .catch(() => ElMessage.warning(`新建${$props.modalConfig.titleTip}失败`))
        .finally(() => (dialogVisible.value = false))
    } else {
      systemStore
        .editPageDataAction($props.modalConfig.pageName, editData.value.id, { ...formData, ...otherFomrDate })
        .then(() => ElMessage.success(`更新${$props.modalConfig.titleTip}成功`))
        .catch(() => ElMessage.warning(`更新${$props.modalConfig.titleTip}失败`))
        .finally(() => (dialogVisible.value = false))
    }
  }

  async function cancel() {
    await nextTick()
    formRef.value?.resetFields()
    $emits('reOtherInfo')
    dialogVisible.value = false
  }

  defineExpose({
    setDialogVisible
  })
</script>

<style lang="scss" scoped>
  .form {
    padding: 0 20px;
    .el-form-item,
    .el-select {
      width: 100%;
    }
  }
</style>
